เพิ่มความเร็วเว็บไซต์และประสบการณ์ผู้ใช้ด้วยเทคนิคการเพิ่มประสิทธิภาพ JavaScript: การแบ่งโค้ดและการประเมินแบบ Lazy เรียนรู้วิธีและเวลาที่จะใช้แต่ละวิธีเพื่อให้ได้ผลลัพธ์ที่ดีที่สุด
การเพิ่มประสิทธิภาพ JavaScript: การแบ่งโค้ดเทียบกับการประเมินแบบ Lazy
ในภูมิทัศน์ดิจิทัลปัจจุบัน ประสิทธิภาพของเว็บไซต์เป็นสิ่งสำคัญยิ่ง เวลาในการโหลดช้าอาจนำไปสู่ผู้ใช้ที่หงุดหงิด อัตราการตีกลับที่สูงขึ้น และท้ายที่สุดคือผลกระทบด้านลบต่อธุรกิจของคุณ JavaScript แม้ว่าจำเป็นสำหรับการสร้างประสบการณ์เว็บแบบไดนามิกและโต้ตอบได้ มักจะเป็นคอขวดหากไม่ได้รับการจัดการอย่างระมัดระวัง เทคนิคที่มีประสิทธิภาพสองอย่างสำหรับการเพิ่มประสิทธิภาพ JavaScript คือ การแบ่งโค้ด และ การประเมินแบบ Lazy คู่มือฉบับสมบูรณ์นี้จะเจาะลึกแต่ละเทคนิค สำรวจวิธีการทำงาน ประโยชน์ ข้อเสีย และเวลาที่จะใช้เพื่อให้ได้ผลลัพธ์ที่ดีที่สุด
ทำความเข้าใจความจำเป็นในการเพิ่มประสิทธิภาพ JavaScript
แอปพลิเคชันเว็บสมัยใหม่มักจะพึ่งพา JavaScript อย่างมากเพื่อให้ฟังก์ชันการทำงานที่หลากหลาย อย่างไรก็ตาม เมื่อแอปพลิเคชันมีความซับซ้อนมากขึ้น จำนวนโค้ด JavaScript ก็เพิ่มขึ้น ทำให้ขนาดบันเดิลใหญ่ขึ้น บันเดิลขนาดใหญ่นี้อาจส่งผลกระทบอย่างมากต่อเวลาในการโหลดหน้าเว็บเริ่มต้น เนื่องจากเบราว์เซอร์จำเป็นต้องดาวน์โหลด แยกวิเคราะห์ และเรียกใช้โค้ดทั้งหมดก่อนที่หน้าเว็บจะโต้ตอบได้
พิจารณาแพลตฟอร์มอีคอมเมิร์ซขนาดใหญ่ที่มีคุณสมบัติมากมาย เช่น การกรองผลิตภัณฑ์ ฟังก์ชันการค้นหา การตรวจสอบสิทธิ์ผู้ใช้ และแกลเลอรีผลิตภัณฑ์แบบโต้ตอบได้ คุณสมบัติทั้งหมดนี้ต้องใช้โค้ด JavaScript จำนวนมาก หากไม่มีการเพิ่มประสิทธิภาพที่เหมาะสม ผู้ใช้อาจประสบปัญหาเวลาในการโหลดช้า โดยเฉพาะอย่างยิ่งบนอุปกรณ์มือถือหรือการเชื่อมต่ออินเทอร์เน็ตที่ช้า ซึ่งอาจนำไปสู่ประสบการณ์ผู้ใช้ที่เป็นลบและการสูญเสียลูกค้า
ดังนั้น การเพิ่มประสิทธิภาพ JavaScript ไม่ใช่แค่รายละเอียดทางเทคนิค แต่เป็นส่วนสำคัญในการมอบประสบการณ์ผู้ใช้ที่เป็นบวกและบรรลุเป้าหมายทางธุรกิจ
การแบ่งโค้ด: การแบ่งบันเดิลขนาดใหญ่
การแบ่งโค้ดคืออะไร
การแบ่งโค้ด คือเทคนิคที่แบ่งโค้ด JavaScript ของคุณออกเป็นส่วนย่อยหรือบันเดิลที่เล็กลงและจัดการได้ง่ายขึ้น แทนที่จะโหลดโค้ดทั้งหมดของแอปพลิเคชันล่วงหน้า เบราว์เซอร์จะดาวน์โหลดเฉพาะโค้ดที่จำเป็นสำหรับการโหลดหน้าเว็บเริ่มต้นเท่านั้น ส่วนย่อยของโค้ดที่ตามมาจะถูกโหลดตามความต้องการ เมื่อผู้ใช้โต้ตอบกับส่วนต่างๆ ของแอปพลิเคชัน
ลองนึกภาพร้านหนังสือ แทนที่จะพยายามยัดหนังสือทุกเล่มที่ขายเข้าไปในหน้าต่างด้านหน้า ทำให้ใครๆ ก็มองเห็นอะไรไม่ชัดเจน พวกเขาจะแสดงตัวเลือกที่คัดสรรมาอย่างดี หนังสือที่เหลือจะถูกเก็บไว้ที่อื่นในร้านและจะถูกดึงออกมาเมื่อลูกค้าขอโดยเฉพาะ การแบ่งโค้ดทำงานในลักษณะเดียวกัน โดยแสดงเฉพาะโค้ดที่จำเป็นสำหรับมุมมองเริ่มต้น และดึงโค้ดอื่นตามต้องการ
การแบ่งโค้ดทำงานอย่างไร
การแบ่งโค้ดสามารถนำไปใช้ได้ในหลายระดับ:
- การแบ่งจุดเริ่มต้น: เกี่ยวข้องกับการสร้างจุดเริ่มต้นที่แยกจากกันสำหรับส่วนต่างๆ ของแอปพลิเคชันของคุณ ตัวอย่างเช่น คุณอาจมีจุดเริ่มต้นที่แยกจากกันสำหรับแอปพลิเคชันหลัก แดชบอร์ดผู้ดูแลระบบ และหน้าโปรไฟล์ผู้ใช้
- การแบ่งตามเส้นทาง: เทคนิคนี้จะแบ่งโค้ดตามเส้นทางของแอปพลิเคชัน แต่ละเส้นทางสอดคล้องกับส่วนย่อยของโค้ดเฉพาะที่โหลดเฉพาะเมื่อผู้ใช้นำทางไปยังเส้นทางนั้น
- การนำเข้าแบบไดนามิก: การนำเข้าแบบไดนามิกช่วยให้คุณสามารถโหลดโมดูลตามความต้องการ ณ รันไทม์ ซึ่งให้การควบคุมอย่างละเอียดว่าจะโหลดโค้ดเมื่อใด ช่วยให้คุณเลื่อนการโหลดโค้ดที่ไม่สำคัญออกไปจนกว่าจะจำเป็นจริงๆ
ประโยชน์ของการแบ่งโค้ด
- ปรับปรุงเวลาในการโหลดเริ่มต้น: การลดขนาดบันเดิลเริ่มต้น การแบ่งโค้ดจะปรับปรุงเวลาในการโหลดหน้าเว็บเริ่มต้นอย่างมาก นำไปสู่ประสบการณ์ผู้ใช้ที่เร็วขึ้นและตอบสนองได้ดีขึ้น
- ลดแบนด์วิดท์เครือข่าย: การโหลดเฉพาะโค้ดที่จำเป็นจะลดปริมาณข้อมูลที่ต้องถ่ายโอนผ่านเครือข่าย ช่วยประหยัดแบนด์วิดท์สำหรับทั้งผู้ใช้และเซิร์ฟเวอร์
- ปรับปรุงการใช้แคช: ส่วนย่อยของโค้ดที่เล็กลงมีแนวโน้มที่จะถูกแคชโดยเบราว์เซอร์มากขึ้น ลดความจำเป็นในการดาวน์โหลดอีกครั้งในการเข้าชมครั้งต่อๆ ไป
- ประสบการณ์ผู้ใช้ที่ดีขึ้น: เวลาในการโหลดที่เร็วขึ้นและแบนด์วิดท์เครือข่ายที่ลดลงมีส่วนช่วยให้ประสบการณ์ผู้ใช้ราบรื่นและสนุกสนานยิ่งขึ้น
ตัวอย่าง: React กับ React.lazy และ Suspense
ใน React การแบ่งโค้ดสามารถนำไปใช้ได้อย่างง่ายดายโดยใช้ React.lazy และ Suspense React.lazy ช่วยให้คุณนำเข้าคอมโพเนนต์แบบไดนามิก ในขณะที่ Suspense มีวิธีแสดง UI สำรอง (เช่น สปินเนอร์โหลด) ขณะที่กำลังโหลดคอมโพเนนต์
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
กำลังโหลด... }>
ในตัวอย่างนี้ OtherComponent จะถูกโหลดเฉพาะเมื่อมีการเรนเดอร์ ขณะที่กำลังโหลด ผู้ใช้จะเห็นข้อความ "กำลังโหลด..."
เครื่องมือสำหรับการแบ่งโค้ด
- Webpack: ตัวรวมโมดูลยอดนิยมที่รองรับเทคนิคการแบ่งโค้ดต่างๆ
- Rollup: ตัวรวมโมดูลอื่นที่เน้นการสร้างบันเดิลขนาดเล็กและมีประสิทธิภาพ
- Parcel: ตัวรวมแบบศูนย์การกำหนดค่าที่จัดการการแบ่งโค้ดโดยอัตโนมัติ
- Vite: เครื่องมือสร้างที่ใช้ประโยชน์จากโมดูล ES เนทีฟเพื่อการพัฒนาที่รวดเร็วและการสร้างเวอร์ชันที่ปรับให้เหมาะสม
การประเมินแบบ Lazy: การเลื่อนการคำนวณ
การประเมินแบบ Lazy คืออะไร
การประเมินแบบ Lazy หรือที่เรียกว่าการประเมินแบบเลื่อน คือเทคนิคการเขียนโปรแกรมที่การประเมินนิพจน์จะล่าช้าจนกว่าจะจำเป็นต้องใช้ค่าจริงๆ กล่าวอีกนัยหนึ่ง การคำนวณจะดำเนินการเฉพาะเมื่อจำเป็นต้องใช้ผลลัพธ์ แทนที่จะคำนวณอย่างกระตือรือร้นล่วงหน้า
ลองนึกภาพว่าคุณกำลังเตรียมอาหารหลายคอร์ส คุณจะไม่ทำอาหารทุกจานพร้อมกัน แต่คุณจะเตรียมอาหารแต่ละจานเมื่อถึงเวลาเสิร์ฟ การประเมินแบบ Lazy ทำงานในลักษณะเดียวกัน โดยดำเนินการคำนวณเฉพาะเมื่อจำเป็นต้องใช้ผลลัพธ์
การประเมินแบบ Lazy ทำงานอย่างไร
ใน JavaScript การประเมินแบบ Lazy สามารถนำไปใช้ได้โดยใช้เทคนิคต่างๆ:
- ฟังก์ชัน: การห่อหุ้มนิพจน์ในฟังก์ชันช่วยให้คุณเลื่อนการประเมินจนกว่าจะมีการเรียกใช้ฟังก์ชัน
- ตัวสร้าง: ตัวสร้างมีวิธีสร้างตัววนซ้ำที่สร้างค่าตามความต้องการ
- Memoization: Memoization เกี่ยวข้องกับการแคชผลลัพธ์ของการเรียกใช้ฟังก์ชันที่มีค่าใช้จ่ายสูง และส่งคืนผลลัพธ์ที่แคชไว้เมื่ออินพุตเดียวกันเกิดขึ้นอีกครั้ง
- Proxies: Proxies สามารถใช้เพื่อสกัดกั้นการเข้าถึงคุณสมบัติและเลื่อนการคำนวณค่าคุณสมบัติจนกว่าจะมีการเข้าถึงจริงๆ
ประโยชน์ของการประเมินแบบ Lazy
- ปรับปรุงประสิทธิภาพ: การเลื่อนการคำนวณที่ไม่จำเป็น การประเมินแบบ Lazy สามารถปรับปรุงประสิทธิภาพได้อย่างมาก โดยเฉพาะอย่างยิ่งเมื่อจัดการกับชุดข้อมูลขนาดใหญ่หรือการคำนวณที่ซับซ้อน
- ลดการใช้หน่วยความจำ: การประเมินแบบ Lazy สามารถลดการใช้หน่วยความจำได้โดยหลีกเลี่ยงการสร้างค่ากลางที่ไม่จำเป็นในทันที
- เพิ่มการตอบสนอง: การหลีกเลี่ยงการคำนวณที่ไม่จำเป็นระหว่างการโหลดเริ่มต้น การประเมินแบบ Lazy สามารถเพิ่มการตอบสนองของแอปพลิเคชันได้
- โครงสร้างข้อมูลอนันต์: การประเมินแบบ Lazy ช่วยให้คุณทำงานกับโครงสร้างข้อมูลอนันต์ เช่น รายการหรือสตรีมอนันต์ โดยคำนวณเฉพาะองค์ประกอบที่จำเป็นตามความต้องการ
ตัวอย่าง: การโหลดรูปภาพแบบ Lazy
กรณีการใช้งานทั่วไปสำหรับการประเมินแบบ Lazy คือการโหลดรูปภาพแบบ Lazy แทนที่จะโหลดรูปภาพทั้งหมดบนหน้าเว็บล่วงหน้า คุณสามารถเลื่อนการโหลดรูปภาพที่ไม่ปรากฏในวิวพอร์ตในตอนแรก ซึ่งสามารถปรับปรุงเวลาในการโหลดหน้าเว็บเริ่มต้นได้อย่างมากและลดการใช้แบนด์วิดท์เครือข่าย
function lazyLoadImages() {
const images = document.querySelectorAll('img[data-src]');
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
images.forEach((img) => {
observer.observe(img);
});
}
document.addEventListener('DOMContentLoaded', lazyLoadImages);
ตัวอย่างนี้ใช้ IntersectionObserver API เพื่อตรวจจับเมื่อรูปภาพเข้าสู่วิวพอร์ต เมื่อมองเห็นรูปภาพ แอตทริบิวต์ src จะถูกตั้งค่าเป็นค่าของแอตทริบิวต์ data-src ซึ่งกระตุ้นให้รูปภาพโหลด จากนั้น observer จะยกเลิกการสังเกตรูปภาพเพื่อป้องกันไม่ให้โหลดอีกครั้ง
ตัวอย่าง: Memoization
Memoization สามารถใช้เพื่อเพิ่มประสิทธิภาพการเรียกใช้ฟังก์ชันที่มีค่าใช้จ่ายสูง นี่คือตัวอย่าง:
function memoize(func) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (cache[key]) {
return cache[key];
}
const result = func(...args);
cache[key] = result;
return result;
};
}
function expensiveCalculation(n) {
// จำลองการคำนวณที่ใช้เวลานาน
for (let i = 0; i < 100000000; i++) {
// ทำอะไรบางอย่าง
}
return n * 2;
}
const memoizedCalculation = memoize(expensiveCalculation);
console.time('การเรียกครั้งแรก');
console.log(memoizedCalculation(5)); // การเรียกครั้งแรก - ใช้เวลา
console.timeEnd('การเรียกครั้งแรก');
console.time('การเรียกครั้งที่สอง');
console.log(memoizedCalculation(5)); // การเรียกครั้งที่สอง - ส่งคืนค่าที่แคชไว้ทันที
console.timeEnd('การเรียกครั้งที่สอง');
ในตัวอย่างนี้ ฟังก์ชัน memoize รับฟังก์ชันเป็นอินพุตและส่งคืนฟังก์ชันเวอร์ชันที่ memoized ฟังก์ชันที่ memoized จะแคชผลลัพธ์ของการเรียกก่อนหน้า เพื่อให้การเรียกครั้งต่อๆ ไปด้วยอาร์กิวเมนต์เดียวกันสามารถส่งคืนผลลัพธ์ที่แคชไว้ได้โดยไม่ต้องดำเนินการฟังก์ชันเดิมอีกครั้ง
การแบ่งโค้ดเทียบกับการประเมินแบบ Lazy: ความแตกต่างที่สำคัญ
แม้ว่าทั้งการแบ่งโค้ดและการประเมินแบบ Lazy จะเป็นเทคนิคการเพิ่มประสิทธิภาพที่มีประสิทธิภาพ แต่ก็จัดการกับแง่มุมต่างๆ ของประสิทธิภาพ:
- การแบ่งโค้ด: เน้นการลดขนาดบันเดิลเริ่มต้นโดยการแบ่งโค้ดออกเป็นส่วนย่อยๆ และโหลดตามความต้องการ ส่วนใหญ่ใช้เพื่อปรับปรุงเวลาในการโหลดหน้าเว็บเริ่มต้น
- การประเมินแบบ Lazy: เน้นการเลื่อนการคำนวณค่าจนกว่าจะจำเป็นต้องใช้จริง ส่วนใหญ่ใช้เพื่อปรับปรุงประสิทธิภาพเมื่อจัดการกับการคำนวณที่มีค่าใช้จ่ายสูงหรือชุดข้อมูลขนาดใหญ่
โดยพื้นฐานแล้ว การแบ่งโค้ดจะลดปริมาณโค้ดที่ต้องดาวน์โหลดล่วงหน้า ในขณะที่การประเมินแบบ Lazy จะลดปริมาณการคำนวณที่ต้องดำเนินการล่วงหน้า
เวลาที่จะใช้การแบ่งโค้ดเทียบกับการประเมินแบบ Lazy
การแบ่งโค้ด
- แอปพลิเคชันขนาดใหญ่: ใช้การแบ่งโค้ดสำหรับแอปพลิเคชันที่มีโค้ด JavaScript จำนวนมาก โดยเฉพาะอย่างยิ่งแอปพลิเคชันที่มีหลายเส้นทางหรือคุณสมบัติ
- การปรับปรุงเวลาในการโหลดเริ่มต้น: ใช้การแบ่งโค้ดเพื่อปรับปรุงเวลาในการโหลดหน้าเว็บเริ่มต้นและลดเวลาในการโต้ตอบ
- การลดแบนด์วิดท์เครือข่าย: ใช้การแบ่งโค้ดเพื่อลดปริมาณข้อมูลที่ต้องถ่ายโอนผ่านเครือข่าย
การประเมินแบบ Lazy
- การคำนวณที่มีค่าใช้จ่ายสูง: ใช้การประเมินแบบ Lazy สำหรับฟังก์ชันที่ดำเนินการคำนวณที่มีค่าใช้จ่ายสูงหรือเข้าถึงชุดข้อมูลขนาดใหญ่
- การปรับปรุงการตอบสนอง: ใช้การประเมินแบบ Lazy เพื่อปรับปรุงการตอบสนองของแอปพลิเคชันโดยการเลื่อนการคำนวณที่ไม่จำเป็นระหว่างการโหลดเริ่มต้น
- โครงสร้างข้อมูลอนันต์: ใช้การประเมินแบบ Lazy เมื่อทำงานกับโครงสร้างข้อมูลอนันต์ เช่น รายการหรือสตรีมอนันต์
- การโหลดสื่อแบบ Lazy: ใช้การโหลดแบบ Lazy สำหรับรูปภาพ วิดีโอ และเนื้อหาสื่ออื่นๆ เพื่อปรับปรุงเวลาในการโหลดหน้าเว็บ
การรวมการแบ่งโค้ดและการประเมินแบบ Lazy
ในหลายกรณี สามารถรวมการแบ่งโค้ดและการประเมินแบบ Lazy เพื่อให้ได้ประสิทธิภาพที่ดียิ่งขึ้น ตัวอย่างเช่น คุณอาจใช้การแบ่งโค้ดเพื่อแบ่งแอปพลิเคชันของคุณออกเป็นส่วนย่อยๆ และใช้การประเมินแบบ Lazy เพื่อเลื่อนการคำนวณค่าภายในส่วนย่อยเหล่านั้น
พิจารณาแอปพลิเคชันอีคอมเมิร์ซ คุณสามารถใช้การแบ่งโค้ดเพื่อแบ่งแอปพลิเคชันออกเป็นบันเดิลแยกต่างหากสำหรับหน้าแสดงรายการผลิตภัณฑ์ หน้าผลิตภัณฑ์ และหน้าชำระเงิน จากนั้น ภายในหน้าผลิตภัณฑ์ คุณสามารถใช้การประเมินแบบ Lazy เพื่อเลื่อนการโหลดรูปภาพหรือการคำนวณคำแนะนำผลิตภัณฑ์จนกว่าจะจำเป็นจริงๆ
นอกเหนือจากการแบ่งโค้ดและการประเมินแบบ Lazy: เทคนิคการเพิ่มประสิทธิภาพเพิ่มเติม
แม้ว่าการแบ่งโค้ดและการประเมินแบบ Lazy จะเป็นเทคนิคที่มีประสิทธิภาพ แต่ก็เป็นเพียงสองส่วนของปริศนาเมื่อพูดถึงการเพิ่มประสิทธิภาพ JavaScript ต่อไปนี้คือเทคนิคเพิ่มเติมที่คุณสามารถใช้เพื่อปรับปรุงประสิทธิภาพเพิ่มเติม:
- Minification: ลบอักขระที่ไม่จำเป็น (เช่น ช่องว่าง ความคิดเห็น) ออกจากโค้ดของคุณเพื่อลดขนาด
- Compression: บีบอัดโค้ดของคุณโดยใช้เครื่องมือเช่น Gzip หรือ Brotli เพื่อลดขนาดเพิ่มเติม
- Caching: ใช้ประโยชน์จากการแคชของเบราว์เซอร์และการแคช CDN เพื่อลดจำนวนคำขอไปยังเซิร์ฟเวอร์ของคุณ
- Tree Shaking: ลบโค้ดที่ไม่ได้ใช้ออกจากบันเดิลของคุณเพื่อลดขนาด
- การเพิ่มประสิทธิภาพรูปภาพ: เพิ่มประสิทธิภาพรูปภาพโดยการบีบอัด ปรับขนาดให้มีขนาดที่เหมาะสม และใช้รูปแบบรูปภาพที่ทันสมัยเช่น WebP
- Debouncing and Throttling: ควบคุมอัตราการเรียกใช้ตัวจัดการเหตุการณ์เพื่อป้องกันปัญหาด้านประสิทธิภาพ
- การจัดการ DOM ที่มีประสิทธิภาพ: ลดการจัดการ DOM ให้เหลือน้อยที่สุดและใช้เทคนิคการจัดการ DOM ที่มีประสิทธิภาพ
- Web Workers: ถ่ายโอนงานที่ต้องใช้การคำนวณมากไปยัง web workers เพื่อป้องกันไม่ให้บล็อกเธรดหลัก
สรุป
การเพิ่มประสิทธิภาพ JavaScript เป็นส่วนสำคัญในการมอบประสบการณ์ผู้ใช้ที่เป็นบวกและบรรลุเป้าหมายทางธุรกิจ การแบ่งโค้ด และ การประเมินแบบ Lazy เป็นสองเทคนิคที่มีประสิทธิภาพที่สามารถปรับปรุงประสิทธิภาพได้อย่างมากโดยการลดเวลาในการโหลดเริ่มต้น ลดการใช้แบนด์วิดท์เครือข่าย และเลื่อนการคำนวณที่ไม่จำเป็น การทำความเข้าใจว่าเทคนิคเหล่านี้ทำงานอย่างไรและเวลาที่จะใช้ คุณสามารถสร้างแอปพลิเคชันเว็บที่เร็วขึ้น ตอบสนองได้ดีขึ้น และสนุกสนานยิ่งขึ้น
อย่าลืมพิจารณาข้อกำหนดของแอปพลิเคชันเฉพาะของคุณและใช้เทคนิคที่เหมาะสมที่สุดสำหรับความต้องการของคุณ ตรวจสอบประสิทธิภาพของแอปพลิเคชันของคุณอย่างต่อเนื่องและทำซ้ำในกลยุทธ์การเพิ่มประสิทธิภาพของคุณเพื่อให้แน่ใจว่าคุณกำลังมอบประสบการณ์ผู้ใช้ที่ดีที่สุด Embrace the power of code splitting and lazy evaluation to create web applications that are not only feature-rich but also performant and delightful to use, worldwide.
แหล่งข้อมูลการเรียนรู้เพิ่มเติม
- เอกสารประกอบ Webpack: https://webpack.js.org/
- เอกสารประกอบ Rollup: https://rollupjs.org/guide/en/
- เอกสารประกอบ Vite: https://vitejs.dev/
- MDN Web Docs - Intersection Observer API: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
- Google Developers - เพิ่มประสิทธิภาพการเรียกใช้ JavaScript: https://developers.google.com/web/fundamentals/performance/optimizing-javascript/